const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const AdmZip = require('adm-zip');
const tar = require('tar');
const cors = require('cors');

const app = express();
const PORT = process.env.PORT || 3000;

// 中间件配置
app.use(cors());
app.use(express.json());
app.use(express.static('public'));

// 上传配置
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = path.join(__dirname, 'uploads');
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({ 
  storage: storage,
  limits: { fileSize: 100 * 1024 * 1024 }, // 100MB限制
  fileFilter: (req, file, cb) => {
    const allowedTypes = /zip|tar|gz|tgz/;
    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
    const mimetype = /application\/(zip|x-tar|gzip)/.test(file.mimetype);
    
    if (extname && mimetype) {
      return cb(null, true);
    } else {
      cb(new Error('只允许上传 ZIP 或 TAR 压缩包'));
    }
  }
});

// 路由：文件上传
app.post('/upload', upload.single('codeFile'), (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: '请选择文件上传' });
    }

    const filePath = req.file.path;
    const fileName = req.file.originalname;
    const extractDir = path.join(__dirname, 'extracted', path.parse(fileName).name);

    // 创建解压目录
    if (!fs.existsSync(extractDir)) {
      fs.mkdirSync(extractDir, { recursive: true });
    }

    // 根据文件类型解压
    const ext = path.extname(fileName).toLowerCase();
    
    if (ext === '.zip') {
      const zip = new AdmZip(filePath);
      zip.extractAllTo(extractDir, true);
    } else if (['.tar', '.gz', '.tgz'].includes(ext)) {
      tar.extract({
        file: filePath,
        cwd: extractDir,
        sync: true
      });
    }

    // 清理上传的压缩包
    fs.unlinkSync(filePath);

    // 获取目录结构
    const structure = getDirectoryStructure(extractDir);
    
    res.json({
      success: true,
      message: '文件上传并解压成功',
      projectName: path.parse(fileName).name,
      structure: structure
    });

  } catch (error) {
    console.error('上传处理错误:', error);
    res.status(500).json({ error: error.message });
  }
});

// 路由：获取文件内容
app.get('/file/:projectName/*', (req, res) => {
  try {
    const projectName = req.params.projectName;
    const filePath = req.params[0];
    const fullPath = path.join(__dirname, 'extracted', projectName, filePath);

    if (!fs.existsSync(fullPath)) {
      return res.status(404).json({ error: '文件不存在' });
    }

    if (fs.statSync(fullPath).isDirectory()) {
      const structure = getDirectoryStructure(fullPath);
      return res.json({ type: 'directory', structure });
    }

    const content = fs.readFileSync(fullPath, 'utf-8');
    const ext = path.extname(fullPath).toLowerCase();
    
    res.json({
      type: 'file',
      content: content,
      language: getLanguageByExtension(ext),
      path: filePath
    });

  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 路由：运行代码
app.post('/run/:projectName', (req, res) => {
  try {
    const projectName = req.params.projectName;
    const { filePath, language } = req.body;
    const fullPath = path.join(__dirname, 'extracted', projectName, filePath);

    if (!fs.existsSync(fullPath)) {
      return res.status(404).json({ error: '文件不存在' });
    }

    const { spawn } = require('child_process');
    let command, args;

    // 根据语言类型设置运行命令
    switch (language) {
      case 'javascript':
        command = 'node';
        args = [fullPath];
        break;
      case 'python':
        command = 'python3';
        args = [fullPath];
        break;
      case 'java':
        command = 'java';
        args = [fullPath.replace('.java', '')];
        break;
      case 'go':
        command = 'go';
        args = ['run', fullPath];
        break;
      case 'rust':
        command = 'rustc';
        args = [fullPath, '-o', '/tmp/temp_binary'];
        break;
      case 'php':
        command = 'php';
        args = [fullPath];
        break;
      default:
        return res.status(400).json({ error: '不支持的语言类型' });
    }

    const process = spawn(command, args, { cwd: path.dirname(fullPath) });
    let output = '';
    let error = '';

    process.stdout.on('data', (data) => {
      output += data.toString();
    });

    process.stderr.on('data', (data) => {
      error += data.toString();
    });

    process.on('close', (code) => {
      res.json({
        success: code === 0,
        output: output,
        error: error,
        exitCode: code
      });
    });

  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 辅助函数：获取目录结构
function getDirectoryStructure(dirPath) {
  const structure = {};
  
  function buildStructure(currentPath, currentObj) {
    const items = fs.readdirSync(currentPath);
    
    items.forEach(item => {
      const itemPath = path.join(currentPath, item);
      const stat = fs.statSync(itemPath);
      
      if (stat.isDirectory()) {
        currentObj[item] = { type: 'directory', children: {} };
        buildStructure(itemPath, currentObj[item].children);
      } else {
        currentObj[item] = {
          type: 'file',
          path: path.relative(path.join(__dirname, 'extracted'), itemPath)
        };
      }
    });
  }
  
  buildStructure(dirPath, structure);
  return structure;
}

// 辅助函数：根据扩展名获取语言类型
function getLanguageByExtension(ext) {
  const languageMap = {
    '.js': 'javascript',
    '.jsx': 'javascript',
    '.ts': 'typescript',
    '.tsx': 'typescript',
    '.py': 'python',
    '.java': 'java',
    '.go': 'go',
    '.rs': 'rust',
    '.php': 'php',
    '.html': 'html',
    '.css': 'css',
    '.json': 'json',
    '.md': 'markdown',
    '.txt': 'text'
  };
  
  return languageMap[ext] || 'text';
}

// 启动服务器
app.listen(PORT, () => {
  console.log(`本地代码上传助手运行在 http://localhost:${PORT}`);
  console.log('请将你的代码压缩为 ZIP 或 TAR 格式后拖拽上传');
});
